package com.caption.api.thread;

import java.time.LocalDate;
import java.util.*;
import java.util.concurrent.*;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.zip.CRC32;

public class Main {

    public static void main(String[] args) throws Exception {
       /* test03();
        test01();
        thenCompose();*/
        test02();
        test05();
    }




    private static void test03(){
        List<String> a1 = Arrays.asList("a","b","c");
        a1.forEach(s->{
            Main.print(s);
        });
        a1.forEach(Main::print);
    }


    private static void print(String st){
        System.out.println(st);
    }



    private static void thenCompose() throws Exception {
        CompletableFuture<Integer> f = CompletableFuture.supplyAsync(new Supplier<Integer>() {
            @Override
            public Integer get() {
                int t = new Random().nextInt(3);
                System.out.println("t1="+t);
                return t;
            }
        }).thenCompose(new Function<Integer, CompletionStage<Integer>>() {
            @Override
            public CompletionStage<Integer> apply(Integer param) {
                return CompletableFuture.supplyAsync(new Supplier<Integer>() {
                    @Override
                    public Integer get() {
                        int t = param *2;
                        System.out.println("t2="+t);
                        return t;
                    }
                });
            }

        });
        System.out.println("thenCompose result : "+f.get());
    }



    public static void test01() throws ExecutionException, InterruptedException {
      Executor executors = new ThreadPoolExecutor(4,4,60L,TimeUnit.SECONDS,new ArrayBlockingQueue<>(200));
      CompletableFuture<Void> future = CompletableFuture.runAsync(()->{
          System.out.println("runAsync没有返回值");
      });
      future.get();
    }


    public static void test02(){
        List<User> list =new ArrayList();
        list.add(new User("zhangsan",20));
        list.add(new User("lisi",30));
        Executor executor = new ThreadPoolExecutor(5,10,60L, TimeUnit.SECONDS,new ArrayBlockingQueue<>(200));
        String[] arr = list.stream().map(user -> user.getName()).toArray(String[]::new);
        Arrays.stream(arr).forEach(s-> System.out.println(s));
    }

    //多个任务同时执行时等待所有任务都完成后执行下面过程
    public static void test05(){
        List<User> list =new ArrayList();
        list.add(new User("zhangsan",20));
        list.add(new User("lisi",30));
        list.add(new User("wangwu",30));
        Executor executor = new ThreadPoolExecutor(5,10,60L, TimeUnit.SECONDS,new ArrayBlockingQueue<>(200));
        List<String> result = new ArrayList<>();
        CompletableFuture[] cfs  =list.stream().map(u->{
            //thenApply
            CompletableFuture future  = CompletableFuture.supplyAsync(()->{
                System.out.println( u.getName() + "执行线程" +Thread.currentThread().getName());
              return Main.learn(u,list);
              //thenApply将完成任务的结果交给下个任务，并且是在同一条线程下面执行的
          },executor).thenApply(n->n.toUpperCase())
         .whenComplete((r,e)->{
             result.add(r);
         });
          return future;
        }).toArray(CompletableFuture[]::new);
        CompletableFuture.allOf(cfs).join();
        result.stream().forEach(r-> System.out.println(r));
    }


    public static String learn(User u,List<User>list){
     /*   System.out.println("list="+list);*/
        return u.getName();
    }



    public static String buildOrderNo(String businessType, Long bizCorpId) {
        /**
         * 规则：
         * 年1位（0-9，超过用字母补全）
         * 月日3位（一年中第几天+100,101-466）
         * 业务类型1位（超过用字母补）
         * 时间戳后4位（时间戳精确到秒）
         * 随机数1位
         * B端userID后2位
         * 校验位1位（前面crc32取个位数
         */
        int year =  Calendar.getInstance().get(Calendar.YEAR);
        String orderNo = String.format("%01d%03d%s%04d%01d%02d",
                year % 10,
                LocalDate.now().getDayOfYear() + 100,
                businessType,
                System.currentTimeMillis() / 1000 % 10000,
                new Random().nextInt(10),
                bizCorpId.longValue() % 100);
        System.out.println(orderNo);
        CRC32 crc32 = new CRC32();
        crc32.update(orderNo.getBytes());
        System.out.println(crc32.getValue());
        orderNo = String.format("%s%s",orderNo,Math.abs(crc32.getValue() % 10));
        return orderNo;
    }

}
